//`timescale 1ns / 1ps
`define DLY #1
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    09:57:02 12/04/2017
// Design Name:
// Module Name:    pcie8311
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module pcie8311(
	input					clk,
	input					ads_n,
	input					blast_n,
	input			[31:2]	la,
	input					lhold,
	output	reg				lholda,
	input					lwr_n,
	inout			[31:0]	PXI_LD,
	output	reg      		ready_n,
	input					data_valid,

	output	reg		[31:0]	data_latch,
	output	reg				addr_en,
	output	reg				wren,
	output	reg				rden,
	output	reg		[31:0]	addr,
	output	reg				pcie_busy,
	output					response_finish	//
);

//总线占用请求及响应电路模块（始终响应请求）
always@(posedge clk)
begin
	lholda <= lhold;
end

reg[2:0] current_state;
reg[2:0] next_state;
localparam	IDLE			= 3'h0;
localparam	WAIT0			= 3'h1;
localparam	ADDR_LATCH		= 3'h2;
localparam	WAIT1			= 3'h3;
localparam	WAIT2			= 3'h4;
localparam	VALID			= 3'h5;
localparam	COMMU_END		= 3'h6;

assign response_finish = (current_state == VALID)? 1'b1 : 1'b0;

always@(posedge clk)
begin
	current_state <=`DLY  next_state;
end

always@(*)
begin
	case(current_state)
	IDLE:begin
			if(!ads_n)
				next_state = WAIT0;
			else
				next_state = current_state;
		end
	WAIT0:begin
			next_state = ADDR_LATCH;
		end
	ADDR_LATCH:begin
			if(wren == 1 && rden == 0)
				next_state = VALID;
			else if(wren == 0 && rden == 1)
				next_state = WAIT1;
			else
				next_state = current_state;
		end
	WAIT1:begin
			next_state = WAIT2;
		end
	WAIT2:begin
			if(data_valid)
				next_state = VALID;
			else
				next_state = WAIT2;
		end
	VALID:begin
			next_state = COMMU_END;
		end
	COMMU_END:begin
//			if(blast_n)
				next_state = IDLE;
//			else
//				next_state = current_state;
		end
	default:begin
			next_state = IDLE;
		end
	endcase
end

always@(posedge clk)
begin
	case(next_state)
	IDLE:begin
			ready_n		<= `DLY 1;
			addr_en		<= `DLY 0;
			wren		<= `DLY 0;
			rden		<= `DLY 0;
			pcie_busy	<= `DLY 0;
		end
	WAIT0:begin
			addr_en		<= `DLY 0;
			wren		<= `DLY 0;
			rden		<= `DLY 0;
			ready_n		<= `DLY 1;
			pcie_busy	<= `DLY 0;
		end
	ADDR_LATCH:begin
			addr_en		<= `DLY 1;
//			addr		<= `DLY {la,2'b0};
			addr		<= `DLY la;
			pcie_busy	<= `DLY 1;
			data_latch	<= `DLY PXI_LD;
			if(lwr_n)
			begin
				wren	<= `DLY 1;
				rden	<= `DLY 0;
				ready_n	<= `DLY 0;
			end
			else
			begin
				wren	<= `DLY 0;
				rden	<= `DLY 1;
				ready_n	<= `DLY 1;
			end
		end
	WAIT1:begin
			ready_n		<= `DLY 1;
			addr_en		<= `DLY 0;
			addr		<= `DLY addr;
			data_latch	<= `DLY data_latch;
			wren		<= `DLY 0;
			rden		<= `DLY 0;
			pcie_busy	<= `DLY 1;
		end
	WAIT2:begin
			ready_n		<= `DLY 1;
			addr_en		<= `DLY 0;
			addr		<= `DLY addr;
			data_latch	<= `DLY data_latch;
			wren		<= `DLY 0;
			rden		<= `DLY 0;
			pcie_busy	<= `DLY 1;
		end
	VALID:begin
			ready_n		<= `DLY 0;
			addr_en		<= `DLY 0;
			addr		<= `DLY addr;
			data_latch	<= `DLY data_latch;
			wren		<= `DLY 0;
			rden		<= `DLY 0;
			pcie_busy	<= `DLY 1;
		end
	COMMU_END:begin
			ready_n		<= `DLY 1;
			addr_en		<= `DLY 0;
			addr		<= `DLY addr;
			data_latch	<= `DLY data_latch;
			wren		<= `DLY 0;
			rden		<= `DLY 0;
			pcie_busy	<= `DLY 0;
		end

	default:;

	endcase
end

endmodule
